package com.vip.elastic.controller;


import com.vip.common.response.RestResponse;
import com.vip.common.response.RestResponses;
import com.vip.elastic.entity.DocumentBean;
import com.vip.elastic.service.IDocumentBeanService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * DocumentBean 控制器
 *
 * @author wgb
 * @date 2020/11/10 10:56
 */
@Slf4j
@RestController
@RequestMapping("/api/doc")
@RequiredArgsConstructor
public class DocumentBeanController {

    private final IDocumentBeanService documentBeanService;

    /**
     * 分页查询
     *
     * @return
     */
    @GetMapping("/page")
    public RestResponse<List<DocumentBean>> getCount(@RequestParam Integer pageNo, @RequestParam Integer pageSize
            , @RequestParam(required = false) String content, @RequestParam(required = false) String firstCode
            , @RequestParam(required = false) String secondCode, @RequestParam(required = false) Integer type) {
        return RestResponses.newResponseFromResult(documentBeanService.getList(pageNo, pageSize, content, firstCode, secondCode, type));
    }

    /**
     * 查询所有
     *
     * @return
     */
    @GetMapping("/all")
    public RestResponse<Iterator<DocumentBean>> all() {
        return RestResponses.newResponseFromResult(documentBeanService.findAll());
    }

    /**
     * 根据给定的字段列表的值的分词查询分词中包含给定的值的文档
     * 待查询的字段类型为text会分词
     * 待查询的值会分词
     *
     * @return
     */
    @PostMapping("/match")
    public RestResponse<Iterator<DocumentBean>> matchQuery(@RequestParam String field, @RequestParam String value) {
        return RestResponses.newResponseFromResult(documentBeanService.matchQuery(field, value));
    }

    /**
     * 根据给定的字段的值的分词查询分词中包含给定的值的文档
     * 待查询的字段类型为text会分词
     * 待查询的值会分词
     *
     * @return
     */
    @GetMapping("/commonTerms")
    public RestResponse<Iterator<DocumentBean>> commonTermsQuery(@RequestParam String field, @RequestParam String value) {
        return RestResponses.newResponseFromResult(documentBeanService.commonTermsQuery(field, value));
    }

    /**
     * 根据给定的字段的值的分词查询分词中包含给定的值的文档，匹配的字段分词所在位置必须和待查询的值的分词位置一致
     * 待查询的字段类型为text会分词
     * 待查询的值会分词
     *
     * @return
     */
    @PostMapping("/multiMatch")
    public RestResponse<Iterator<DocumentBean>> multiMatchQuery(@RequestParam String value, @RequestBody String... fields) {
        return RestResponses.newResponseFromResult(documentBeanService.multiMatchQuery(value, fields));
    }

    /**
     * 根据给定的字段的值的分词查询分词中包含给定的值的文档，匹配的字段分词所在位置必须和待查询的值的分词位置一致
     * 待查询的字段类型为text会分词
     * 待查询的值会分词
     *
     * @return
     */
    @PostMapping("/matchPhrase")
    public RestResponse<Iterator<DocumentBean>> matchPhraseQuery(@RequestParam String field, @RequestParam String value) {
        return RestResponses.newResponseFromResult(documentBeanService.matchPhraseQuery(field, value));
    }

    /**
     * 根据给定的字段的值的分词查询分词中包含给定的值的文档，匹配的字段分词所在位置必须和待查询的值的分词位置一致，
     * 并且会将待查询的值的最后一个词作为前缀去进行查询
     * 待查询的字段类型为text会分词
     * 待查询的值会分词
     *
     * @return
     */
    @PostMapping("/phrasePrefix")
    public RestResponse<Iterator<DocumentBean>> matchPhrasePrefix(@RequestParam String field, @RequestParam String value) {
        return RestResponses.newResponseFromResult(documentBeanService.matchPhrasePrefix(field, value));
    }

    /**
     * 对子查询的结果做去重合并，score沿用子查询score的最大值
     * 待查询的字段类型为text会分词
     * 待查询的值会分词
     *
     * @return
     */
    @PostMapping("/disMaxQuery")
    public RestResponse<Iterator<DocumentBean>> disMaxQuery(@RequestParam String field, @RequestParam String value) {
        return RestResponses.newResponseFromResult(documentBeanService.disMaxQuery(field, value));
    }

    /**
     * 根据给定的idArray查询文档
     *
     * @return
     */
    @PostMapping("/idsQuery")
    public RestResponse<Iterator<DocumentBean>> idsQuery(@RequestBody List<Long> ids) {
        return RestResponses.newResponseFromResult(documentBeanService.idsQuery(ids));
    }

    /**
     * 根据给定的字段的值的分词查询分词中包含给定的值的文档
     * 待查询的字段类型为text会分词
     * 待查询的值不会分词
     *
     * @return
     */
    @PostMapping("/termQuery")
    public RestResponse<Iterator<DocumentBean>> termQuery(@RequestBody String field, @RequestParam String value) {
        return RestResponses.newResponseFromResult(documentBeanService.termQuery(field, value));
    }

    /**
     * 根据给定的字段的值的分词查询分词中包含给定的值在纠正指定次数（默认是2）后的文档
     * 待查询的字段不会分词
     * 待查询的值不会分词
     *
     * @return
     */
    @PostMapping("/fuzzyQuery")
    public RestResponse<Iterator<DocumentBean>> fuzzyQuery(@RequestParam String field, @RequestParam String value, @RequestParam Integer fuzzy) {
        return RestResponses.newResponseFromResult(documentBeanService.fuzzyQuery(field, value, fuzzy));
    }

    /**
     * 根据给定的字段的值的分词查询分词中包含前缀为给定的值的文档
     * 待查询的字段类型为text会分词
     * 待查询的值不会分词
     *
     * @return
     */
    @PostMapping("/prefixQuery")
    public RestResponse<Iterator<DocumentBean>> prefixQuery(@RequestParam String field, @RequestParam String value) {
        return RestResponses.newResponseFromResult(documentBeanService.prefixQuery(field, value));
    }

    /**
     * 根据给定的字段的值的分词查询分词中在指定范围内的文档
     * 待查询的字段类型为text会分词
     * 待查询的值不会分词
     *
     * @return
     */
    @PostMapping("/rangeQuery")
    public RestResponse<Iterator<DocumentBean>> rangeQuery(@RequestParam String field, @RequestParam String gte, @RequestParam String lte) {
        return RestResponses.newResponseFromResult(documentBeanService.rangeQuery(field, gte, lte));
    }

    /**
     * 根据给定的字段的值的分词查询分词中包含待查询的值（包含通配符，*：任意字符；?：任意一个字符）的文档
     * 注意：尽量别用*或?开头
     * 待查询的字段类型为text会分词
     * 待查询的值不会分词
     *
     * @return
     */
    @PostMapping("/wildcardQuery")
    public RestResponse<Iterator<DocumentBean>> wildcardQuery(@RequestParam String field, @RequestParam String value) {
        return RestResponses.newResponseFromResult(documentBeanService.wildcardQuery(field, value));
    }

    /**
     * 根据给定的字段的值的分词查询分词中符合正则表达式的文档
     * 注意：最好在使用正则前，加上匹配的前缀
     * 待查询的字段类型为text会分词
     * 待查询的正则表达式不会分词
     *
     * @return
     */
    @PostMapping("/regexpQuery")
    public RestResponse<Iterator<DocumentBean>> regexpQuery(@RequestParam String field, @RequestParam String regexp) {
        return RestResponses.newResponseFromResult(documentBeanService.regexpQuery(field, regexp));
    }

    /**
     * 根据给定的字段的值的分词查询分词中符合查询字符串的文档
     * 待查询的字段类型为text会分词
     * 查询字符串会分词
     *
     * @param value 查询字符串（支持的通配符。支持通过AND OR NOT ！进行布尔运算。+：代表必须含有  -：代表不能含有）
     * @return
     */
    @PostMapping("/queryStringQuery")
    public RestResponse<Iterator<DocumentBean>> queryStringQuery(@RequestBody List<String> fields, @RequestParam String value) {
        return RestResponses.newResponseFromResult(documentBeanService.queryStringQuery(fields, value));
    }

    /**
     * 根据给定的字段的值的分词查询分词中符合查询字符串的文档
     * 待查询的字段类型为text会分词
     * 查询字符串会分词
     *
     * @param value 查询字符串（支持的通配符。支持通过AND OR NOT ！进行布尔运算。+：代表必须含有  -：代表不能含有）
     * @return
     */
    @PostMapping("/simpleQueryStringQuery")
    public RestResponse<Iterator<DocumentBean>> simpleQueryStringQuery(@RequestBody List<String> fields, @RequestParam String value) {
        return RestResponses.newResponseFromResult(documentBeanService.simpleQueryStringQuery(fields, value));
    }

    /**
     * 返回positive query的查询结果，如果positive query的查询结果也满足negative query，则改变其_source的值
     *
     * @return
     */
    @PostMapping("/boostingQuery")
    public RestResponse<Iterator<DocumentBean>> boostingQuery(@RequestParam String field, @RequestParam String value) {
        return RestResponses.newResponseFromResult(documentBeanService.boostingQuery(field, value));
    }

    /**
     * 返回满足bool下所有query的结果
     *
     * @return
     */
    @PostMapping("/boolQuery")
    public RestResponse<Iterator<DocumentBean>> boolQuery(@RequestBody Map<String, List<String>> params) {
        return RestResponses.newResponseFromResult(documentBeanService.boolQuery(params));
    }

    /**
     * 等同于 term query ，但与其他Span查询一起使用
     *
     * @return
     */
    @PostMapping("/spanTermQuery")
    public RestResponse<Iterator<DocumentBean>> spanTermQuery(@RequestParam String field, @RequestParam String value) {
        return RestResponses.newResponseFromResult(documentBeanService.spanTermQuery(field, value));
    }

    /**
     * 查询出待查询的值在待查询的字段的值的分词中前end个位置的文档
     *
     * @return
     */
    @PostMapping("/spanFirstQuery")
    public RestResponse<Iterator<DocumentBean>> spanFirstQuery(@RequestParam String field, @RequestParam String value) {
        return RestResponses.newResponseFromResult(documentBeanService.spanFirstQuery(field, value));
    }

    /**
     * 几个span query匹配的值的跨度必须在0-slop范围内，匹配的值的顺序必须和span query顺序一样
     * 注意：所有span query的待查询的字段必须为同一个，不然会报异常
     *
     * @return
     */
    @PostMapping("/spanNearQuery")
    public RestResponse<Iterator<DocumentBean>> spanNearQuery(@RequestParam String field, @RequestParam String value) {
        return RestResponses.newResponseFromResult(documentBeanService.spanNearQuery(field, value));
    }

    /**
     * 把include query查询结果中符合exclude query的文档排除后返回结果
     * 注意：include query和exclude query的待查询的字段必须为同一个，不然会报异常
     * 注意：include query和exclude query的span query都为span_term好像不会被拦截
     *
     * @return
     */
    @PostMapping("/spanNotQuery")
    public RestResponse<Iterator<DocumentBean>> spanNotQuery(@RequestParam String field, @RequestParam String value) {
        return RestResponses.newResponseFromResult(documentBeanService.spanNotQuery(field, value));
    }

    /**
     * 返回与任何span query匹配的文档
     * 注意：所有span query的待查询的字段必须为同一个，不然会报异常
     *
     * @return
     */
    @PostMapping("/spanOrQuery")
    public RestResponse<Iterator<DocumentBean>> spanOrQuery(@RequestParam String field, @RequestParam String value) {
        return RestResponses.newResponseFromResult(documentBeanService.spanOrQuery(field, value));
    }

    /**
     * 查找符合big query条件且包含little query的文档
     * 注意：所有span query的待查询的字段必须为同一个，不然会报异常
     *
     * @return
     */
    @PostMapping("/spanWithinQuery")
    public RestResponse<Iterator<DocumentBean>> spanWithinQuery(@RequestParam String field, @RequestParam String value) {
        return RestResponses.newResponseFromResult(documentBeanService.spanWithinQuery(field, value));
    }

    /**
     * 查找符合big query条件的文档，之后筛选出包含little query的文档
     * 注意：所有span query的待查询的字段必须为同一个，不然会报异常
     *
     * @return
     */
    @PostMapping("/spanContainingQuery")
    public RestResponse<Iterator<DocumentBean>> spanContainingQuery(@RequestParam String field, @RequestParam String value) {
        return RestResponses.newResponseFromResult(documentBeanService.spanContainingQuery(field, value));
    }

    /**
     * 查找满足条件的文档
     *
     * @return
     */
    @PostMapping("/spanMultiTermQueryBuilder")
    public RestResponse<Iterator<DocumentBean>> spanMultiTermQueryBuilder(@RequestParam String field, @RequestParam String value) {
        return RestResponses.newResponseFromResult(documentBeanService.spanMultiTermQueryBuilder(field, value));
    }

    /**
     * 具体不清楚是干嘛的，好像只能用于span query下，猜测是从已查询到的文档中过滤出符合该query的文档
     * 注意：所有span query的待查询的字段必须为同一个，不然会报异常
     *
     * @return
     */
    @PostMapping("/fieldMaskingSpanQuery")
    public RestResponse<Iterator<DocumentBean>> fieldMaskingSpanQuery(@RequestParam String field, @RequestParam String value) {
        return RestResponses.newResponseFromResult(documentBeanService.fieldMaskingSpanQuery(field, value));
    }

    /**
     * 查询满足条件的文档并返回指定的_source
     *
     * @return
     */
    @PostMapping("/constantScoreQuery")
    public RestResponse<Iterator<DocumentBean>> constantScoreQuery(@RequestParam String field, @RequestParam String value) {
        return RestResponses.newResponseFromResult(documentBeanService.constantScoreQuery(field, value));
    }

    /**
     * 查询满足条件的文档但不对_source进行计算
     *
     * @return
     */
    @PostMapping("/functionScoreQueryNoFunction")
    public RestResponse<Iterator<DocumentBean>> functionScoreQueryNoFunction(@RequestParam String field, @RequestParam String value) {
        return RestResponses.newResponseFromResult(documentBeanService.functionScoreQueryNoFunction(field, value));
    }

    /**
     * 查询满足条件的文档并对_source进行计算
     * 这个太过复杂，详情请看https://www.jianshu.com/p/f164f127bf33
     *
     * @return
     */
    @PostMapping("/functionScoreQuery")
    public RestResponse<Iterator<DocumentBean>> functionScoreQuery(@RequestBody List<String> values) {
        return RestResponses.newResponseFromResult(documentBeanService.functionScoreQuery(values));
    }

    /**
     * 根据待查询字段array查询包含待查询的值array的文档
     * 相关参数解释地址：https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-mlt-query.html
     * es7.6测试查不到数据，不知道是什么原因
     *
     * @return
     */
    @PostMapping("/moreLikeThisQuery")
    public RestResponse<Iterator<DocumentBean>> moreLikeThisQuery(@RequestBody List<String> values) {
        return RestResponses.newResponseFromResult(documentBeanService.moreLikeThisQuery(values));
    }

    /**
     * 用于nested嵌套类型的查询
     * nested嵌套类型详细说明请看：https://blog.csdn.net/laoyang360/article/details/82950393
     *
     * @return
     */
    @PostMapping("/nestedQuery")
    public RestResponse<Iterator<DocumentBean>> nestedQuery(@RequestParam String field, @RequestParam String value) {
        return RestResponses.newResponseFromResult(documentBeanService.nestedQuery(field, value));
    }

    /**
     * 根据给定的字段的值的分词查询分词中包含给定的值array的文档
     * 待查询的字段类型为text会分词
     * 待查询的值不会分词
     *
     * @return
     */
    @PostMapping("/termsQuery")
    public RestResponse<Iterator<DocumentBean>> termsQuery(@RequestParam String field, @RequestBody List<String> value) {
        return RestResponses.newResponseFromResult(documentBeanService.termsQuery(field, value));
    }

    /**
     * 根据查询语句的base编码格式进行查询，例如：
     * eyJ0ZXJtIiA6IHsgIuW+heafpeivoueahOWtl+autSI6ICLlvoXmn6Xor6LnmoTlgLwiIH19 对应 {"term" : { "待查询的字段": "待查询的值" }}
     *
     * @return
     */
    @PostMapping("/wrapperQuery")
    public RestResponse<Iterator<DocumentBean>> wrapperQuery(@RequestParam String value) {
        return RestResponses.newResponseFromResult(documentBeanService.wrapperQuery(value));
    }

    /**
     * 根据文档类型查询，在7.0中已经被弃用
     *
     * @return
     */
    @PostMapping("/typeQuery")
    public RestResponse<Iterator<DocumentBean>> typeQuery(@RequestParam String type) {
        return RestResponses.newResponseFromResult(documentBeanService.typeQuery(type));
    }

    /**
     * 根据给定的字段的值的分词查询分词中包含指定索引下指定id的文档的指定字段的值
     * 待查询的字段类型为text会分词
     * 待查询的值不会分词词
     *
     * @return
     */
    @PostMapping("/termsLookupQuery")
    public RestResponse<Iterator<DocumentBean>> termsLookupQuery(@RequestParam String index, @RequestParam String type
            , @RequestParam String id, @RequestParam String field) {
        return RestResponses.newResponseFromResult(documentBeanService.termsLookupQuery(index, type, id, field));
    }

    /**
     * 作为查询运行的脚本，具体使用方法见：
     * https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting-using.html
     * 例子，查询指定字段的值大于指定值的数据：
     *
     * @return
     */
    @PostMapping("/scriptQuery")
    public RestResponse<Iterator<DocumentBean>> scriptQuery(@RequestParam String value, @RequestParam String source) {
        return RestResponses.newResponseFromResult(documentBeanService.scriptQuery(value, source));
    }

    /**
     * 查询文档中包含待查询字段的数据
     *
     * @return
     */
    @PostMapping("/existsQuery")
    public RestResponse<Iterator<DocumentBean>> existsQuery(@RequestParam String field) {
        return RestResponses.newResponseFromResult(documentBeanService.existsQuery(field));
    }

}


